# -*- coding: utf-8 -*-
"""
Created on Wed Jan 02 18:28:20 2013

@author: Winand
"""

#ip -o -4 addr show eth0
#2: eth0    inet 192.168.1.166/24 brd 192.168.1.255 scope global eth0
#arp -na
#? (192.168.1.105) at 00:e0:4d:45:21:fa [ether] on eth0
#? (192.168.1.1) at bc:ae:c5:c4:93:a7 [ether] on eth0
#ip neigh
#192.168.1.105 dev eth0 lladdr 00:e0:4d:45:21:fa REACHABLE
#192.168.1.1 dev eth0 lladdr bc:ae:c5:c4:93:a7 REACHABLE
#192.168.1.203 dev eth0 lladdr 38:ec:e4:85:1c:dc PROBE
#--
#192.168.1.203 dev eth0  INCOMPLETE

#x="2: eth0    inet 192.168.1.166/24 brd 192.168.1.255 scope global eth0"
#y=x.split()
#ip, brd = None, None
#for i,v in enumerate(y):
#    if i==len(y)-1: break
#    if v=="inet": ip=y[i+1].split("/")
#    elif v=="brd": brd=y[i+1]
#print ip, brd
#exit()

import socket
from webapi import http, config
from webapi.log import error
from webapi.general import hasKeys
from settings import SRV_CONF_ROOT_PATH, SRV_ROOT_PATH
from webapi.general import makeBackgroundCall
from general import *

name="Wake-on-LAN (WOL)"
description="Service sends WOL packet to a chosen machine MAC address inside local network"
path="wake"

#TODO: remove test cache V
arpcache="""WL-BCAEC5C493A7 (192.168.1.1) at bc:ae:c5:c4:93:a7 [ether] on eth0
Winand-HPC (192.168.1.105) at 00:e0:4d:45:21:fa [ether] on eth0
? (192.168.1.243) at e0:b9:a5:1a:38:d2 [ether] on eth0"""

def __getArpCache():
    data = [arpcache, 0]
#    try:
#        p=subprocess.Popen(["arp", "-a"], stdout=subprocess.PIPE)
#        data = p.communicate()
#    except: return "" #no arp util
    dat_chunks = [i.split() for i in data[0].split("\n")]
    names, ips, macs = [], [], []
    for i, v in enumerate(dat_chunks):
        ips.append(v[1][1:-1])
        names.append(v[0] if v[0] != "?" else ips[-1])
        macs.append(v[3])
    return (names, ips, macs)

def __dispMacAddr(addr): return "-".join(["%02x" % ord(i) for i in addr])

def getPage(options, resp):
    mac_list = config.cget("wake/mac_list", {})
    mac_list_disp = map(__dispMacAddr, mac_list.keys())
    if len(options):
        if options[0] == "wake" and hasKeys(resp.query, ('addr',)):
            mac_val=resp.query['addr'].value
            makeBackgroundCall("wake", {"mac_str": mac_val})
    http.templateResponse(resp, "tpl_svc_wake_home.html", \
                        {'page_desc': description,
                        'root_path': '/'+SRV_ROOT_PATH+'/'+path,
                        'mac_list_len': len(mac_list),
                        'mac_list': mac_list_disp,
                        'mac_list_desc': mac_list.values(),
                        'brd_addr': getBroadcastAddress(),
                        })
                        
#TODO: optimize mac list read/write
def getConfPage(options, resp):
    mac_list = config.cget("wake/mac_list", {})
    input_mac, input_desc = "", ""
    last_err = ""
    if len(options):
        if options[0] == "add" and hasKeys(resp.post_query, ('mac', 'desc')):
            mac_val=resp.post_query['mac'].value
            mac = parseDispMacAddr(mac_val)
            if mac:
                mac_list[mac] = resp.post_query['desc'].value
                config.cset("wake/mac_list", mac_list)
            else: last_err = "Cannot add " + mac_val + ". Wrong MAC address"
        elif options[0] == "choose" and hasKeys(resp.query, ('mac', 'desc')):
            input_mac = resp.query['mac'].value
            input_desc = resp.query['desc'].value
        elif options[0] == "del" and hasKeys(resp.query, 'mac'):
            mac_s = resp.query['mac'].value
            mac = parseDispMacAddr(mac_s)
            if mac in mac_list:
                del mac_list[mac]
                config.cset("wake/mac_list", mac_list)
            else: last_err = "Cannot delete " + mac_s + ". Not found"
        elif options[0] == "broadcast" and hasKeys(resp.post_query, 'addr'):
            try:
                addr = socket.inet_aton(resp.post_query['addr'].value)
                config.cset("wake/broadcast", addr)
            except socket.error: last_err = "Invalid IP address in broadcast field"
    mac_list_disp = map(__dispMacAddr, mac_list.keys())
            
    arpc = __getArpCache()
    http.templateResponse(resp, "tpl_svc_wake_conf.html", \
                        {'brd_addr': getBroadcastAddress(),
                        'srv_name': path,
                        'root_path': '/'+SRV_CONF_ROOT_PATH+'/'+path,
                        'arp_names': arpc[0],
                        'arp_macs': arpc[2],
                        'arp_len': len(arpc[0]),
                        'mac_list_len': len(mac_list),
                        'mac_list': mac_list_disp,
                        'mac_list_desc': mac_list.values(),
                        'input_mac_val': input_mac,
                        'input_mac_desc': input_desc,
                        'lasterror': last_err,
                        })
                        
def getAjaxChunk(options, resp):
    if len(options):
        if options[0] == "get_arp_cache":
            arpc = __getArpCache()
            http.templateResponse(resp, "tpl_svc_wake_conf.html", \
                                {'root_path': '/'+SRV_CONF_ROOT_PATH+'/'+path,
                                'arp_names': arpc[0],
                                'arp_macs': arpc[2],
                                'arp_len': len(arpc[0]),
                                }, ajaxblock=options[0])
        else: error("unknown ajax request", options[0])
    else: error("empty ajax request")
